/**
 * 
 */
package com.gr.staffpm.utils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.joda.time.DateTime;

import com.gr.staffpm.pages.schedule.model.Event;


/**
 * @author Graham Rhodes 29 Mar 2011 12:51:41
 */
public class ListSortUtils {

    //private static Logger log = LoggerFactory.getLogger(ListSortUtils.class);

    /**
     * Merge sort a list of events by date. Earliest being first.
     * 
     * @param events a list of Event items.
     */
    public static void sortEventsByDate(List<Event> events) {
        //Already sorted?
        if (events.size() < 2)
            return;
        mergeSortEvents((ArrayList<Event>) events, 0, events.size() - 1);
    }

    public static void mergeSortEvents(ArrayList<Event> events, int left, int right) {
        if (left < right) {
            int center = (left + right) / 2;
            mergeSortEvents(events, left, center);
            mergeSortEvents(events, center + 1, right);
            mergeEvents(events, left, center + 1, right);
        }
    }

    /**
     * Merges two sorted halves of a sublist of events.
     * 
     * @param events a list of Event items.
     * @param tmp a list to place the merged result.
     * @param leftPos the left-most index of the sublist.
     * @param rightPos the index of the start of the second half.
     * @param rightEnd the right-most index of the sublist.
     */
    private static void mergeEvents(ArrayList<Event> events, int leftPos, int rightPos, int rightEnd) {
        int leftEnd = rightPos - 1;
        int tmpPos = leftPos;
        int numElements = rightEnd - leftPos + 1;
        Event[] tmpArray = new Event[events.size()];

        while (leftPos <= leftEnd && rightPos <= rightEnd) {
            if (events.get(leftPos).startsBefore(events.get(rightPos)))
                tmpArray[tmpPos++] = events.get(leftPos++);
            else
                tmpArray[tmpPos++] = events.get(rightPos++);
        }

        // Copy rest of first half
        while (leftPos <= leftEnd) {
            tmpArray[tmpPos++] = events.get(leftPos++);
        }

        // Copy rest of right half
        while (rightPos <= rightEnd) {
            tmpArray[tmpPos++] = events.get(rightPos++);
        }

        // Copy tmp back
        for (int i = 0; i < numElements; i++, rightEnd--) {
            events.set(rightEnd, tmpArray[rightEnd]);
        }
    }

    public static List<List<Event>> sortEventsByDayAndLength(List<Event> events, DateTime weekStartDate, boolean onlyAllDay, boolean onlyNotAllDay) {

        assert (events != null && events.isEmpty());

        List<List<Event>> sortedEventLists = new ArrayList<List<Event>>();
        List<Event> sundayEvents = new ArrayList<Event>(), mondayEvents = new ArrayList<Event>(), tuesdayEvents = new ArrayList<Event>();
        List<Event> wednesdayEvents = new ArrayList<Event>(), thursdayEvents = new ArrayList<Event>(), fridayEvents = new ArrayList<Event>(), saturdayEvents = new ArrayList<Event>();

        //log.info("Events to sort: " + events.size());
        //log.info("Week Start: " + weekStartDate.toString("dd MMM yyyy"));
        for (Event event : events) {
            if (onlyAllDay && !event.isAllDay())
                continue;
            if (onlyNotAllDay && event.isAllDay())
                continue;
            //log.info("Event: " + event.getTitle() + " start: " + event.getStart().toString("dd MMM yyyy") + " end: " + event.getEnd().toString("dd MMM yyyy"));
            if (event.startsOnOrBefore(weekStartDate)) {
                sundayEvents.add(event);
                //log.info("Added event to sunday");
            }
            if (event.startsOnOrBefore(weekStartDate.plusDays(1))) {
                mondayEvents.add(event);
                //log.info("Added event to monday");
            }
            if (event.startsOnOrBefore(weekStartDate.plusDays(2))) {
                tuesdayEvents.add(event);
                //log.info("Added event to tuesday");
            }
            if (event.startsOnOrBefore(weekStartDate.plusDays(3))) {
                wednesdayEvents.add(event);
                //log.info("Added event to wednesday");
            }
            if (event.startsOnOrBefore(weekStartDate.plusDays(4))) {
                thursdayEvents.add(event);
                //log.info("Added event to thursday");
            }
            if (event.startsOnOrBefore(weekStartDate.plusDays(5))) {
                fridayEvents.add(event);
                //log.info("Added event to friday");
            }
            if (event.startsOnOrBefore(weekStartDate.plusDays(6))) {
                saturdayEvents.add(event);
                //log.info("Added event to saturday");
            }
        }

        Collections.sort(sundayEvents);
        Collections.sort(mondayEvents);
        Collections.sort(tuesdayEvents);
        Collections.sort(wednesdayEvents);
        Collections.sort(thursdayEvents);
        Collections.sort(fridayEvents);
        Collections.sort(saturdayEvents);

        sortedEventLists.add(sundayEvents);
        sortedEventLists.add(mondayEvents);
        sortedEventLists.add(tuesdayEvents);
        sortedEventLists.add(wednesdayEvents);
        sortedEventLists.add(thursdayEvents);
        sortedEventLists.add(fridayEvents);
        sortedEventLists.add(saturdayEvents);

        return sortedEventLists;
    }

}
